﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using CrawlerCore;
using HtmlAgilityPack;
using System.Net;

using System.Threading;
using System.Threading.Tasks;
using System.IO;
using WCrawlerLib;

namespace WCrawler
{
    public partial class GetCountries : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        public void AddNewLocation(string locationName, string key, string flagurl)
        {
            LinqDataClassesDataContext dc = new LinqDataClassesDataContext();
            var query = from p in dc.Locations
                        where p.LocationName == locationName.ToLower()
                        select p;
            if (query.Count() == 0) //Nếu không tìm  thấy thì insert Language
            {
                Location loc = new Location
                {
                    LocationName = locationName,
                    Key = key,
                    FlagUrl = flagurl
                };
                dc.Locations.InsertOnSubmit(loc);
                dc.SubmitChanges();
            }
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            //detect alexa rank
            BrowserSession_General br = new BrowserSession_General();
            br.Get(@"http://www.alexa.com/topsites/countries");
            string xpath = ".//div[@class='categories top']//li//a";
            string national = "", key = "", flagurl = "";
            foreach (HtmlNode node in br.HtmlDoc.DocumentNode.SelectNodes(xpath))
            {
                national = node.SelectNodes("./text()")[0].InnerHtml;
                key = node.Attributes["href"].Value.Split(new char[] {'/'})[3];
                flagurl = @"http://icache.alexa.com/images/flags/" + key.ToLower() +".png";
                AddNewLocation(national,key,flagurl);
            }
        }

        public void AddNewStatusCode(int code, string name)
        {
            LinqDataClassesDataContext dc = new LinqDataClassesDataContext();
            //var query = from p in dc.StatusCodes
            //            where p.Code == code
            //            select p;
            //if (query.Count() == 0) //Nếu không tìm  thấy thì insert
            //{
            StatusCode sc = new StatusCode
            {
                Code = code,
                Name = name
            };
            dc.StatusCodes.InsertOnSubmit(sc);
            dc.SubmitChanges();
            //}
        }

        public void AddNewLanguage(string name)
        {
            LinqDataClassesDataContext dc = new LinqDataClassesDataContext();
            Language lang = new Language
            {
                LanguageName = name
            };
            dc.Languages.InsertOnSubmit(lang);
            dc.SubmitChanges();
        }
        protected void Button2_Click(object sender, EventArgs e)
        {
            int code = -1;
            string name = "";
            foreach (object item in Enum.GetValues(typeof(HttpStatusCode)))
            {
                code = (int)item;
                name = item.ToString();
                AddNewStatusCode(code, name);
            }
        }

        protected void btnGetLanguages_Click(object sender, EventArgs e)
        {
            BrowserSession_General br = new BrowserSession_General();
            br.Get(@"http://translate.google.com/");
            //string xpath = "./html/body/div[4]/table/tbody/tr/td/div/div/div/text()";
            string xpath = ".//meta[@name = 'description']";
            string content = "";
            SortedDictionary<string, string> lang = new SortedDictionary<string, string>();
            foreach (HtmlNode node in br.HtmlDoc.DocumentNode.SelectNodes(xpath))
            {
                string replace = "Google&#39;s free online language translation service instantly translates text and web pages. This translator supports: ";
                content = node.Attributes["content"].Value.Replace(replace,"");
                string[] list = content.Split(new char[] { ',' });
                foreach(string item in list)
                    lang.Add(item.Trim(),item.Trim());
            }

            foreach(KeyValuePair<string,string> k in lang)
                AddNewLanguage(k.Key);
        }

        public void TaskParallel1(){
            // The sum of these elements is 40.
            int[] input = { 4, 1, 6, 2, 9, 5, 10, 3 };
            int sum = 0;

            try
            {
                Parallel.ForEach(
                        input,					            // source collection
                        () => 0,					        // thread local initializer
                        (n, loopState, localSum) =>		    // body
                        {
                            localSum += n;
                            Response.Write("Thread=" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + ", n=" + n.ToString()+ ", localSum=" + localSum.ToString() + "<br />");
                            return localSum;
                        },
                        (localSum) => Interlocked.Add(ref sum, localSum)					// thread local aggregator
                    );

                Response.Write("Sum=" + sum.ToString() + "<br />");
            }
            // No exception is expected in this example, but if one is still thrown from a task,
            // it will be wrapped in AggregateException and propagated to the main thread.
            catch (AggregateException e)
            {
                Response.Write("Parallel.ForEach has thrown an exception. THIS WAS NOT EXPECTED. Message:" + e.Message + "<br/>");
            }
        }
        

        protected void btnTaskParallel_Click(object sender, EventArgs e)
        {
            TaskParallel1();
        }

        public void test1(HtmlDocument doc)
        {
            var query = from table in doc.DocumentNode.SelectNodes("//table").Cast<HtmlNode>()
                        where table.SelectNodes("tr").Count >= 3 && table.SelectNodes("th|thead").Count >= 1
                        from row in table.SelectNodes("tr").Cast<HtmlNode>()
                        where row.SelectNodes("th|td").Count >= 3
                        from cell in row.SelectNodes("th|td").Cast<HtmlNode>()
                        select new { Table = table.Id, CellText = cell.InnerText };

            foreach (var cell in query)
            {
                Console.WriteLine("{0}: {1}", cell.Table, cell.CellText);
            }
        }

        public void test3(HtmlDocument doc)
        {

        }

        /// <summary>
        /// Lấy chuỗi header của forum
        /// </summary>
        /// <param name="doc"></param>
        public void test2(HtmlDocument doc)
        {
            int num;
            //string xpath = ".//table[count(.//thead)>=1 and count(.//thead/tr/td)>1]";
            string xpath = ".//table[count(./thead)>=1 and count(./thead/tr/td)>1]";
            HtmlNodeCollection nodeCollection = doc.DocumentNode.SelectNodes(xpath);
            num = nodeCollection.Count;
            foreach (HtmlNode table in nodeCollection)
            {
                Response.Write("<table>");
                Response.Write("<thead>");
                Response.Write("<tr>");

                HtmlNodeCollection nc = table.SelectNodes("//thead/tr/th|//thead/tr/td");
                num = nc.Count;
                foreach (HtmlNode th in nc)
                {
                    if (th.Name == "th" || th.Name == "td")
                    {
                        Response.Write("<th>" + th.InnerHtml + "</th>");
                    }
                }

                Response.Write("</tr>");
                Response.Write("</thead>");
                Response.Write("</table>");
            }
        }

        /// <summary>
        /// Xử lý từng column một để xác định chính xác nội dung của mỗi column
        ///  .//table[count(.//thead)>=1 and count(.//tr)>=3 and count(.//td)>=3]
        ///  .//table[(count(.//thead)>=1 or count(.//th) >=1) and count(.//tr)>=3 and count(.//td)>=3]//thead//td
        ///  .//table[(count(.//thead)>=1 or count(.//th) >=1) and count(.//tr)>=3 and count(.//td)>=3]//th/text()
        /// </summary>
        /// <param name="doc"></param>
        public void IndetifyHeaderColumn(HtmlDocument doc)
        {
            //string xpath = ".//table[count(.//thead)>=1 and count(.//thead/tr/td)>1]";
            string xpath = ".//table[count(./thead)>=1 and count(./thead/tr/td)>1]";
            HtmlNodeCollection nodeCollection = doc.DocumentNode.SelectNodes(xpath);
            if (nodeCollection == null)
            {
                xpath = ".//table[count(.//th)>=1]";
                nodeCollection = doc.DocumentNode.SelectNodes(xpath);
                Response.Write("<table><tr>");
                foreach (HtmlNode th in doc.DocumentNode.SelectNodes("//th"))
                {
                    Response.Write(th.OuterHtml);
                }

                Response.Write("</tr></table>");
            }
            else
            {
                int columns = 0;
                HtmlNodeCollection rowCollection;
                foreach (HtmlNode table in nodeCollection)
                {
                    Response.Write("<table>");
                    foreach (HtmlNode thead in table.ChildNodes)
                    {
                        if (thead.Name == "thead")
                        {
                            Response.Write("<thead>");
                            foreach (HtmlNode tr in thead.ChildNodes)
                            {
                                if (tr.Name == "tr")
                                {
                                    Response.Write("<tr>");
                                    foreach (HtmlNode th in tr.ChildNodes)
                                    {
                                        if (th.Name == "th" || th.Name == "td")
                                        {
                                            columns++;
                                            Response.Write("<th>" + th.InnerHtml + "</th>");
                                        }
                                    }
                                    Response.Write("</tr>");
                                }
                            }
                            Response.Write("</thead>");
                            break;
                        }
                    }
                    rowCollection = table.SelectNodes("//tr[count(./td)>=" + columns + "]");
                    foreach (HtmlNode tr in rowCollection)
                    {
                        if (tr.Name == "tr")
                        {
                            Response.Write("<tr>");
                            foreach (HtmlNode td in tr.ChildNodes)
                            {
                                if (tr.Name == "td")
                                {
                                    Response.Write("<td>" + td.InnerHtml + "</td>");
                                }
                            }
                            Response.Write("</tr>");
                        }
                    }
                    Response.Write("</table>");
                }
            }
        }

        protected void btnParseHtmlTable_Click(object sender, EventArgs e)
        {
            HtmlAgilityPack.HtmlDocument doc;
            BrowserSession_General browser = new BrowserSession_General();
            //http://code-projects.com/forum/
            //doc = browser.Get(@"http://www.final4ever.com" + "/index.php");
            doc = browser.Get(@"http://www.warez-junkie.co.uk" + "/index.php");

            //TEST 2
            //IndetifyHeaderColumn(doc);
            test2(doc);
        }

        protected void btnReadFile_Click(object sender, EventArgs e)
        {
            StreamReader fp = File.OpenText(@"E:\Programming\CRAWLER\My Code\WCrawler\PostNewThreadSample.txt");
            string txtSubject = "Total Training for Adobe Photoshop CS5 Extended Essentials";
            string txtMessage = fp.ReadToEnd();
            fp.Close();

            Post obj = new Post();
            obj.AddNewPost(txtSubject, txtMessage);
        }

        protected void btnDecodeUrl_Click(object sender, EventArgs e)
        {
            txtResultUrl.Text = HttpUtility.UrlDecode(txtUrl.Text);
        }

        protected void btnEncodeUrl_Click(object sender, EventArgs e)
        {
            txtResultUrl.Text = HttpUtility.UrlPathEncode(txtUrl.Text);
        }
    }
}